{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.5/dist-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n",
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "from __future__ import print_function\n",
    "\n",
    "from keras.models import Model\n",
    "from keras.layers import Input, LSTM, Dense\n",
    "from keras.optimizers import Adam\n",
    "import numpy as np\n",
    "import keras.backend as K\n",
    "from pathlib import Path\n",
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['/job:localhost/replica:0/task:0/device:GPU:0']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "K.tensorflow_backend._get_available_gpus()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw_path = Path('../../data/raw/')\n",
    "math_data = raw_path/'v1.0'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "extrapolate  interpolate  train-easy  train-hard  train-medium\r\n"
     ]
    }
   ],
   "source": [
    "!ls '{math_data}'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_easy_data = math_data/'train-easy'\n",
    "train_easy_sample = train_easy_data/'algebra__linear_1d.txt'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "56"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "datasets = !ls '{train_easy_data}'\n",
    "len(datasets)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "batch_size = 1024  # Batch size for training.\n",
    "epochs = 75  # Number of epochs to train for.\n",
    "latent_dim = 256  # Latent dimensionality of the encoding space.\n",
    "data_path = train_easy_sample"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(str(data_path), 'r', encoding='utf-8') as f:\n",
    "    lines = f.read().split('\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['-3', '-1', '-8', '-4', '-4', '7', '1', '-1', '2', '-3']\n"
     ]
    }
   ],
   "source": [
    "print(lines[1::2][:10])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Vectorize the data.\n",
    "input_texts = []\n",
    "target_texts = []\n",
    "input_characters = set()\n",
    "target_characters = set()\n",
    "with open(str(data_path), 'r', encoding='utf-8') as f:\n",
    "    lines = f.read().split('\\n')[:-1]\n",
    "\n",
    "input_texts = lines[0::2]\n",
    "target_texts = ['\\t' + target_text + '\\n' for target_text in lines[1::2]]\n",
    "\n",
    "input_characters = set(\"\".join(input_texts))\n",
    "target_characters = set(\"\".join(target_texts))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\t5\\n'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target_texts[-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of samples: 666666\n",
      "Number of unique input tokens: 43\n",
      "Number of unique output tokens: 13\n",
      "Max sequence length for inputs: 41\n",
      "Max sequence length for outputs: 5\n"
     ]
    }
   ],
   "source": [
    "input_characters = sorted(list(input_characters))\n",
    "target_characters = sorted(list(target_characters))\n",
    "num_encoder_tokens = len(input_characters)\n",
    "num_decoder_tokens = len(target_characters)\n",
    "max_encoder_seq_length = max([len(txt) for txt in input_texts])\n",
    "max_decoder_seq_length = max([len(txt) for txt in target_texts])\n",
    "\n",
    "print('Number of samples:', len(input_texts))\n",
    "print('Number of unique input tokens:', num_encoder_tokens)\n",
    "print('Number of unique output tokens:', num_decoder_tokens)\n",
    "print('Max sequence length for inputs:', max_encoder_seq_length)\n",
    "print('Max sequence length for outputs:', max_decoder_seq_length)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_token_index = dict(\n",
    "    [(char, i) for i, char in enumerate(input_characters)])\n",
    "target_token_index = dict(\n",
    "    [(char, i) for i, char in enumerate(target_characters)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'\\t': 0,\n",
       " '\\n': 1,\n",
       " '-': 2,\n",
       " '0': 3,\n",
       " '1': 4,\n",
       " '2': 5,\n",
       " '3': 6,\n",
       " '4': 7,\n",
       " '5': 8,\n",
       " '6': 9,\n",
       " '7': 10,\n",
       " '8': 11,\n",
       " '9': 12}"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target_token_index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def exact_match_metric(y_true, y_pred):\n",
    "    \n",
    "    # get indices from vectors \n",
    "    y_pred_argmax = tf.argmax(y_pred, axis=-1)\n",
    "    y_true_argmax = tf.argmax(y_true, axis=-1)\n",
    "    \n",
    "    # get mask of rows with no entry\n",
    "    mask = tf.equal(tf.reduce_sum(y_true, axis=-1),0)\n",
    "\n",
    "    pred_match = tf.equal(y_pred_argmax, y_true_argmax)  \n",
    "    \n",
    "    # if no label in y_true, then actual match doesn't matter --> equal=True\n",
    "    pred_match_fixed = tf.where(mask, tf.ones_like(pred_match, dtype=tf.bool), pred_match)\n",
    "\n",
    "    exact_match = tf.reduce_min(tf.to_float(pred_match_fixed), axis=[1])\n",
    "    return tf.reduce_mean(exact_match)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "encoder_input_data = np.zeros(\n",
    "    (len(input_texts), max_encoder_seq_length, num_encoder_tokens),\n",
    "    dtype='float32')\n",
    "decoder_input_data = np.zeros(\n",
    "    (len(input_texts), max_decoder_seq_length, num_decoder_tokens),\n",
    "    dtype='float32')\n",
    "decoder_target_data = np.zeros(\n",
    "    (len(input_texts), max_decoder_seq_length, num_decoder_tokens),\n",
    "    dtype='float32')\n",
    "\n",
    "for i, (input_text, target_text) in enumerate(zip(input_texts, target_texts)):\n",
    "    for t, char in enumerate(input_text):\n",
    "        encoder_input_data[i, t, input_token_index[char]] = 1.\n",
    "    for t, char in enumerate(target_text):\n",
    "        # decoder_target_data is ahead of decoder_input_data by one timestep\n",
    "        decoder_input_data[i, t, target_token_index[char]] = 1.\n",
    "        if t > 0:\n",
    "            # decoder_target_data will be ahead by one timestep\n",
    "            # and will not include the start character.\n",
    "            decoder_target_data[i, t - 1, target_token_index[char]] = 1."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
       "       [0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]],\n",
       "      dtype=float32)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "decoder_target_data[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_token_index = dict(\n",
    "    [(char, i) for i, char in enumerate(input_characters)])\n",
    "target_token_index = dict(\n",
    "    [(char, i) for i, char in enumerate(target_characters)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "encoder_input_data = np.zeros(\n",
    "    (len(input_texts), max_encoder_seq_length, num_encoder_tokens),\n",
    "    dtype='float32')\n",
    "decoder_input_data = np.zeros(\n",
    "    (len(input_texts), max_decoder_seq_length, num_decoder_tokens),\n",
    "    dtype='float32')\n",
    "decoder_target_data = np.zeros(\n",
    "    (len(input_texts), max_decoder_seq_length, num_decoder_tokens),\n",
    "    dtype='float32')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i, (input_text, target_text) in enumerate(zip(input_texts, target_texts)):\n",
    "    for t, char in enumerate(input_text):\n",
    "        encoder_input_data[i, t, input_token_index[char]] = 1.\n",
    "    for t, char in enumerate(target_text):\n",
    "        # decoder_target_data is ahead of decoder_input_data by one timestep\n",
    "        decoder_input_data[i, t, target_token_index[char]] = 1.\n",
    "        if t > 0:\n",
    "            # decoder_target_data will be ahead by one timestep\n",
    "            # and will not include the start character.\n",
    "            decoder_target_data[i, t - 1, target_token_index[char]] = 1."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define an input sequence and process it.\n",
    "encoder_inputs = Input(shape=(None, num_encoder_tokens))\n",
    "encoder = LSTM(latent_dim, return_state=True)\n",
    "encoder_outputs, state_h, state_c = encoder(encoder_inputs)\n",
    "# We discard `encoder_outputs` and only keep the states.\n",
    "encoder_states = [state_h, state_c]\n",
    "\n",
    "# Set up the decoder, using `encoder_states` as initial state.\n",
    "decoder_inputs = Input(shape=(None, num_decoder_tokens))\n",
    "# We set up our decoder to return full output sequences,\n",
    "# and to return internal states as well. We don't use the\n",
    "# return states in the training model, but we will use them in inference.\n",
    "decoder_lstm = LSTM(latent_dim, return_sequences=True, return_state=True)\n",
    "decoder_outputs, _, _ = decoder_lstm(decoder_inputs,\n",
    "                                     initial_state=encoder_states)\n",
    "decoder_dense = Dense(num_decoder_tokens, activation='softmax')\n",
    "decoder_outputs = decoder_dense(decoder_outputs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 533332 samples, validate on 133334 samples\n",
      "Epoch 1/75\n",
      "533332/533332 [==============================] - 39s 73us/step - loss: 0.6248 - exact_match_metric: 0.0520 - val_loss: 0.5752 - val_exact_match_metric: 0.0739\n",
      "Epoch 2/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.5573 - exact_match_metric: 0.0907 - val_loss: 0.5301 - val_exact_match_metric: 0.1210\n",
      "Epoch 3/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.5149 - exact_match_metric: 0.1459 - val_loss: 0.5000 - val_exact_match_metric: 0.1687\n",
      "Epoch 4/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.4828 - exact_match_metric: 0.1860 - val_loss: 0.4692 - val_exact_match_metric: 0.1995\n",
      "Epoch 5/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.4550 - exact_match_metric: 0.2119 - val_loss: 0.4410 - val_exact_match_metric: 0.2270\n",
      "Epoch 6/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.4242 - exact_match_metric: 0.2418 - val_loss: 0.4066 - val_exact_match_metric: 0.2614\n",
      "Epoch 7/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.3799 - exact_match_metric: 0.2843 - val_loss: 0.3591 - val_exact_match_metric: 0.2998\n",
      "Epoch 8/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.3428 - exact_match_metric: 0.3168 - val_loss: 0.3259 - val_exact_match_metric: 0.3352\n",
      "Epoch 9/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.3133 - exact_match_metric: 0.3471 - val_loss: 0.2969 - val_exact_match_metric: 0.3644\n",
      "Epoch 10/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.2895 - exact_match_metric: 0.3732 - val_loss: 0.2781 - val_exact_match_metric: 0.3821\n",
      "Epoch 11/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.2704 - exact_match_metric: 0.3939 - val_loss: 0.2699 - val_exact_match_metric: 0.3928\n",
      "Epoch 12/75\n",
      "533332/533332 [==============================] - 39s 72us/step - loss: 0.2560 - exact_match_metric: 0.4099 - val_loss: 0.2529 - val_exact_match_metric: 0.4106\n",
      "Epoch 13/75\n",
      "533332/533332 [==============================] - 39s 72us/step - loss: 0.2444 - exact_match_metric: 0.4223 - val_loss: 0.2468 - val_exact_match_metric: 0.4191\n",
      "Epoch 14/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.2348 - exact_match_metric: 0.4316 - val_loss: 0.2338 - val_exact_match_metric: 0.4318\n",
      "Epoch 15/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.2267 - exact_match_metric: 0.4396 - val_loss: 0.2302 - val_exact_match_metric: 0.4320\n",
      "Epoch 16/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.2232 - exact_match_metric: 0.4440 - val_loss: 0.2183 - val_exact_match_metric: 0.4476\n",
      "Epoch 17/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.2180 - exact_match_metric: 0.4493 - val_loss: 0.2269 - val_exact_match_metric: 0.4340\n",
      "Epoch 18/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.2157 - exact_match_metric: 0.4521 - val_loss: 0.2164 - val_exact_match_metric: 0.4468\n",
      "Epoch 19/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.2129 - exact_match_metric: 0.4549 - val_loss: 0.2120 - val_exact_match_metric: 0.4500\n",
      "Epoch 20/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.2092 - exact_match_metric: 0.4592 - val_loss: 0.2174 - val_exact_match_metric: 0.4438\n",
      "Epoch 21/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.2076 - exact_match_metric: 0.4625 - val_loss: 0.2092 - val_exact_match_metric: 0.4529\n",
      "Epoch 22/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.2063 - exact_match_metric: 0.4636 - val_loss: 0.2116 - val_exact_match_metric: 0.4511\n",
      "Epoch 23/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.2026 - exact_match_metric: 0.4681 - val_loss: 0.2207 - val_exact_match_metric: 0.4411\n",
      "Epoch 24/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.2019 - exact_match_metric: 0.4692 - val_loss: 0.1943 - val_exact_match_metric: 0.4695\n",
      "Epoch 25/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1995 - exact_match_metric: 0.4713 - val_loss: 0.1999 - val_exact_match_metric: 0.4622\n",
      "Epoch 26/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1980 - exact_match_metric: 0.4735 - val_loss: 0.1989 - val_exact_match_metric: 0.4629\n",
      "Epoch 27/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1978 - exact_match_metric: 0.4739 - val_loss: 0.1943 - val_exact_match_metric: 0.4663\n",
      "Epoch 28/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1950 - exact_match_metric: 0.4784 - val_loss: 0.2077 - val_exact_match_metric: 0.4560\n",
      "Epoch 29/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1955 - exact_match_metric: 0.4787 - val_loss: 0.1945 - val_exact_match_metric: 0.4689\n",
      "Epoch 30/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1930 - exact_match_metric: 0.4809 - val_loss: 0.2154 - val_exact_match_metric: 0.4459\n",
      "Epoch 31/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1925 - exact_match_metric: 0.4823 - val_loss: 0.1904 - val_exact_match_metric: 0.4704\n",
      "Epoch 32/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1921 - exact_match_metric: 0.4829 - val_loss: 0.1909 - val_exact_match_metric: 0.4710\n",
      "Epoch 33/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1905 - exact_match_metric: 0.4863 - val_loss: 0.1880 - val_exact_match_metric: 0.4759\n",
      "Epoch 34/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1905 - exact_match_metric: 0.4864 - val_loss: 0.1912 - val_exact_match_metric: 0.4724\n",
      "Epoch 35/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1895 - exact_match_metric: 0.4892 - val_loss: 0.1875 - val_exact_match_metric: 0.4786\n",
      "Epoch 36/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.1871 - exact_match_metric: 0.4926 - val_loss: 0.1949 - val_exact_match_metric: 0.4678\n",
      "Epoch 37/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1869 - exact_match_metric: 0.4934 - val_loss: 0.1912 - val_exact_match_metric: 0.4747\n",
      "Epoch 38/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1859 - exact_match_metric: 0.4955 - val_loss: 0.1906 - val_exact_match_metric: 0.4751\n",
      "Epoch 39/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1858 - exact_match_metric: 0.4974 - val_loss: 0.1970 - val_exact_match_metric: 0.4678\n",
      "Epoch 40/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1831 - exact_match_metric: 0.5049 - val_loss: 0.2276 - val_exact_match_metric: 0.4557\n",
      "Epoch 41/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1833 - exact_match_metric: 0.5095 - val_loss: 0.1904 - val_exact_match_metric: 0.4896\n",
      "Epoch 42/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.1810 - exact_match_metric: 0.5245 - val_loss: 0.1912 - val_exact_match_metric: 0.5003\n",
      "Epoch 43/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.1753 - exact_match_metric: 0.5671 - val_loss: 0.1845 - val_exact_match_metric: 0.5931\n",
      "Epoch 44/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1587 - exact_match_metric: 0.6491 - val_loss: 0.1500 - val_exact_match_metric: 0.6811\n",
      "Epoch 45/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.1409 - exact_match_metric: 0.7068 - val_loss: 0.1274 - val_exact_match_metric: 0.7423\n",
      "Epoch 46/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.1258 - exact_match_metric: 0.7455 - val_loss: 0.1199 - val_exact_match_metric: 0.7609\n",
      "Epoch 47/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.1127 - exact_match_metric: 0.7770 - val_loss: 0.1129 - val_exact_match_metric: 0.7782\n",
      "Epoch 48/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0992 - exact_match_metric: 0.8056 - val_loss: 0.0930 - val_exact_match_metric: 0.8222\n",
      "Epoch 49/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.0870 - exact_match_metric: 0.8314 - val_loss: 0.0867 - val_exact_match_metric: 0.8316\n",
      "Epoch 50/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.0778 - exact_match_metric: 0.8494 - val_loss: 0.0731 - val_exact_match_metric: 0.8567\n",
      "Epoch 51/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0702 - exact_match_metric: 0.8634 - val_loss: 0.0618 - val_exact_match_metric: 0.8815\n",
      "Epoch 52/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0629 - exact_match_metric: 0.8776 - val_loss: 0.0828 - val_exact_match_metric: 0.8423\n",
      "Epoch 53/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.0603 - exact_match_metric: 0.8820 - val_loss: 0.0590 - val_exact_match_metric: 0.8835\n",
      "Epoch 54/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0571 - exact_match_metric: 0.8883 - val_loss: 0.0514 - val_exact_match_metric: 0.8980\n",
      "Epoch 55/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0544 - exact_match_metric: 0.8928 - val_loss: 0.0466 - val_exact_match_metric: 0.9087\n",
      "Epoch 56/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0529 - exact_match_metric: 0.8954 - val_loss: 0.0492 - val_exact_match_metric: 0.9001\n",
      "Epoch 57/75\n",
      "533332/533332 [==============================] - 39s 72us/step - loss: 0.0504 - exact_match_metric: 0.9004 - val_loss: 0.0473 - val_exact_match_metric: 0.9040\n",
      "Epoch 58/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.0512 - exact_match_metric: 0.8988 - val_loss: 0.0652 - val_exact_match_metric: 0.8727\n",
      "Epoch 59/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0500 - exact_match_metric: 0.9010 - val_loss: 0.0439 - val_exact_match_metric: 0.9109\n",
      "Epoch 60/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0489 - exact_match_metric: 0.9030 - val_loss: 0.0437 - val_exact_match_metric: 0.9132\n",
      "Epoch 61/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0470 - exact_match_metric: 0.9061 - val_loss: 0.0476 - val_exact_match_metric: 0.9043\n",
      "Epoch 62/75\n",
      "533332/533332 [==============================] - 39s 72us/step - loss: 0.0491 - exact_match_metric: 0.9026 - val_loss: 0.0498 - val_exact_match_metric: 0.9000\n",
      "Epoch 63/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0462 - exact_match_metric: 0.9075 - val_loss: 0.0476 - val_exact_match_metric: 0.9030\n",
      "Epoch 64/75\n",
      "533332/533332 [==============================] - 39s 73us/step - loss: 0.0450 - exact_match_metric: 0.9096 - val_loss: 0.0433 - val_exact_match_metric: 0.9127\n",
      "Epoch 65/75\n",
      "533332/533332 [==============================] - 39s 72us/step - loss: 0.0462 - exact_match_metric: 0.9082 - val_loss: 0.0513 - val_exact_match_metric: 0.8981\n",
      "Epoch 66/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0441 - exact_match_metric: 0.9118 - val_loss: 0.1068 - val_exact_match_metric: 0.8506\n",
      "Epoch 67/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0431 - exact_match_metric: 0.9134 - val_loss: 0.0431 - val_exact_match_metric: 0.9143\n",
      "Epoch 68/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0425 - exact_match_metric: 0.9149 - val_loss: 0.0513 - val_exact_match_metric: 0.8988\n",
      "Epoch 69/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.0423 - exact_match_metric: 0.9146 - val_loss: 0.0452 - val_exact_match_metric: 0.9084\n",
      "Epoch 70/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.0423 - exact_match_metric: 0.9148 - val_loss: 0.0428 - val_exact_match_metric: 0.9134\n",
      "Epoch 71/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0421 - exact_match_metric: 0.9151 - val_loss: 0.0434 - val_exact_match_metric: 0.9140\n",
      "Epoch 72/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.0413 - exact_match_metric: 0.9174 - val_loss: 0.0440 - val_exact_match_metric: 0.9116\n",
      "Epoch 73/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0403 - exact_match_metric: 0.9186 - val_loss: 0.0444 - val_exact_match_metric: 0.9112\n",
      "Epoch 74/75\n",
      "533332/533332 [==============================] - 38s 71us/step - loss: 0.0404 - exact_match_metric: 0.9188 - val_loss: 0.0442 - val_exact_match_metric: 0.9091\n",
      "Epoch 75/75\n",
      "533332/533332 [==============================] - 38s 72us/step - loss: 0.0404 - exact_match_metric: 0.9192 - val_loss: 0.0432 - val_exact_match_metric: 0.9111\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.5/dist-packages/keras/engine/network.py:877: UserWarning: Layer lstm_2 was passed non-serializable keyword arguments: {'initial_state': [<tf.Tensor 'lstm_1/while/Exit_2:0' shape=(?, 256) dtype=float32>, <tf.Tensor 'lstm_1/while/Exit_3:0' shape=(?, 256) dtype=float32>]}. They will not be included in the serialized model (and thus will be missing at deserialization time).\n",
      "  '. They will not be included '\n"
     ]
    }
   ],
   "source": [
    "# Define the model that will turn\n",
    "# `encoder_input_data` & `decoder_input_data` into `decoder_target_data`\n",
    "model = Model([encoder_inputs, decoder_inputs], decoder_outputs)\n",
    "\n",
    "# Run training\n",
    "adam = Adam(lr=6e-4, beta_1=0.9, beta_2=0.995, epsilon=1e-9, decay=0.0, amsgrad=False)\n",
    "\n",
    "model.compile(optimizer=adam, loss='categorical_crossentropy', metrics=[exact_match_metric])\n",
    "trian_hist = model.fit([encoder_input_data, decoder_input_data], decoder_target_data,\n",
    "                       batch_size=batch_size,\n",
    "                       epochs=epochs,\n",
    "                       validation_split=0.2\n",
    "                       )\n",
    "# Save model\n",
    "model.save('simple-lstm-2.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Next: inference mode (sampling).\n",
    "# Here's the drill:\n",
    "# 1) encode input and retrieve initial decoder state\n",
    "# 2) run one step of decoder with this initial state\n",
    "# and a \"start of sequence\" token as target.\n",
    "# Output will be the next target token\n",
    "# 3) Repeat with the current target token and current states\n",
    "\n",
    "# Define sampling models\n",
    "encoder_model = Model(encoder_inputs, encoder_states)\n",
    "\n",
    "decoder_state_input_h = Input(shape=(latent_dim,))\n",
    "decoder_state_input_c = Input(shape=(latent_dim,))\n",
    "decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]\n",
    "decoder_outputs, state_h, state_c = decoder_lstm(\n",
    "    decoder_inputs, initial_state=decoder_states_inputs)\n",
    "decoder_states = [state_h, state_c]\n",
    "decoder_outputs = decoder_dense(decoder_outputs)\n",
    "decoder_model = Model(\n",
    "    [decoder_inputs] + decoder_states_inputs,\n",
    "    [decoder_outputs] + decoder_states)\n",
    "\n",
    "# Reverse-lookup token index to decode sequences back to\n",
    "# something readable.\n",
    "reverse_input_char_index = dict(\n",
    "    (i, char) for char, i in input_token_index.items())\n",
    "reverse_target_char_index = dict(\n",
    "    (i, char) for char, i in target_token_index.items())\n",
    "\n",
    "\n",
    "def decode_sequence(input_seq):\n",
    "    # Encode the input as state vectors.\n",
    "    states_value = encoder_model.predict(input_seq)\n",
    "\n",
    "    # Generate empty target sequence of length 1.\n",
    "    target_seq = np.zeros((1, 1, num_decoder_tokens))\n",
    "    # Populate the first character of target sequence with the start character.\n",
    "    target_seq[0, 0, target_token_index['\\t']] = 1.\n",
    "\n",
    "    # Sampling loop for a batch of sequences\n",
    "    # (to simplify, here we assume a batch of size 1).\n",
    "    stop_condition = False\n",
    "    decoded_sentence = ''\n",
    "    while not stop_condition:\n",
    "        output_tokens, h, c = decoder_model.predict(\n",
    "            [target_seq] + states_value)\n",
    "\n",
    "        # Sample a token\n",
    "        sampled_token_index = np.argmax(output_tokens[0, -1, :])\n",
    "        sampled_char = reverse_target_char_index[sampled_token_index]\n",
    "        decoded_sentence += sampled_char\n",
    "\n",
    "        # Exit condition: either hit max length\n",
    "        # or find stop character.\n",
    "        if (sampled_char == '\\n' or\n",
    "           len(decoded_sentence) > max_decoder_seq_length):\n",
    "            stop_condition = True\n",
    "\n",
    "        # Update the target sequence (of length 1).\n",
    "        target_seq = np.zeros((1, 1, num_decoder_tokens))\n",
    "        target_seq[0, 0, sampled_token_index] = 1.\n",
    "\n",
    "        # Update states\n",
    "        states_value = [h, c]\n",
    "\n",
    "    return decoded_sentence"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-\n",
      "Input sentence: Solve 0 = 4*b + b + 15 for b.\n",
      "Decoded sentence: -3\n",
      "\n",
      "-\n",
      "Input sentence: Solve -3*d = -0*d + 3 for d.\n",
      "Decoded sentence: -1\n",
      "\n",
      "-\n",
      "Input sentence: Solve -4*h + 9 = 41 for h.\n",
      "Decoded sentence: -8\n",
      "\n",
      "-\n",
      "Input sentence: Solve 2514*m = 2508*m - 24 for m.\n",
      "Decoded sentence: -6\n",
      "\n",
      "-\n",
      "Input sentence: Solve -7*a + 6*a = 4 for a.\n",
      "Decoded sentence: -4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 288*w - 298*w = -70 for w.\n",
      "Decoded sentence: 7\n",
      "\n",
      "-\n",
      "Input sentence: Solve -14*h = -4*h - 10 for h.\n",
      "Decoded sentence: 1\n",
      "\n",
      "-\n",
      "Input sentence: Solve 5*w + 3 = -2 for w.\n",
      "Decoded sentence: -1\n",
      "\n",
      "-\n",
      "Input sentence: Solve -15*f + 21*f - 12 = 0 for f.\n",
      "Decoded sentence: 2\n",
      "\n",
      "-\n",
      "Input sentence: Solve -22 = 6*c - 4 for c.\n",
      "Decoded sentence: -3\n",
      "\n",
      "-\n",
      "Input sentence: Solve 13*z - 7*z + 30 = 0 for z.\n",
      "Decoded sentence: -5\n",
      "\n",
      "-\n",
      "Input sentence: Solve -4*v + 224 = -32*v for v.\n",
      "Decoded sentence: -8\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 = -4*j - 906 + 894 for j.\n",
      "Decoded sentence: -5\n",
      "\n",
      "-\n",
      "Input sentence: Solve -70*n - 222 = -107*n for n.\n",
      "Decoded sentence: 6\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 = 5*f - 24 + 14 for f.\n",
      "Decoded sentence: 2\n",
      "\n",
      "-\n",
      "Input sentence: Solve 56*l + 25 = 61*l for l.\n",
      "Decoded sentence: 5\n",
      "\n",
      "-\n",
      "Input sentence: Solve 2*y - 9*y = 21 for y.\n",
      "Decoded sentence: -3\n",
      "\n",
      "-\n",
      "Input sentence: Solve -4*d - 14 + 6 = 0 for d.\n",
      "Decoded sentence: -2\n",
      "\n",
      "-\n",
      "Input sentence: Solve -9 = 4*x - 5 for x.\n",
      "Decoded sentence: -1\n",
      "\n",
      "-\n",
      "Input sentence: Solve -30 = -14*r + 8*r for r.\n",
      "Decoded sentence: 5\n",
      "\n",
      "-\n",
      "Input sentence: Solve 36*u - 20 = 52 for u.\n",
      "Decoded sentence: 2\n",
      "\n",
      "-\n",
      "Input sentence: Solve -3*v = -58 + 79 for v.\n",
      "Decoded sentence: -7\n",
      "\n",
      "-\n",
      "Input sentence: Solve 212 = 56*z + 44 for z.\n",
      "Decoded sentence: 3\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 - 16 = -4*m for m.\n",
      "Decoded sentence: 4\n",
      "\n",
      "-\n",
      "Input sentence: Solve -4*f - 56 = -40 for f.\n",
      "Decoded sentence: -4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 = 79*g - 72*g - 63 for g.\n",
      "Decoded sentence: 9\n",
      "\n",
      "-\n",
      "Input sentence: Solve 60*k + 198 = 27*k for k.\n",
      "Decoded sentence: -6\n",
      "\n",
      "-\n",
      "Input sentence: Solve 50 = 10*q - 0*q for q.\n",
      "Decoded sentence: 5\n",
      "\n",
      "-\n",
      "Input sentence: Solve 3*q = -3*q - 18 for q.\n",
      "Decoded sentence: -3\n",
      "\n",
      "-\n",
      "Input sentence: Solve 4*i - 28 = 18*i for i.\n",
      "Decoded sentence: -2\n",
      "\n",
      "-\n",
      "Input sentence: Solve 57 = -15*y - 4*y for y.\n",
      "Decoded sentence: -3\n",
      "\n",
      "-\n",
      "Input sentence: Solve 2*v + 5 - 13 = 0 for v.\n",
      "Decoded sentence: 4\n",
      "\n",
      "-\n",
      "Input sentence: Solve -2 + 48 = -23*w for w.\n",
      "Decoded sentence: -2\n",
      "\n",
      "-\n",
      "Input sentence: Solve u + 8 = 5*u for u.\n",
      "Decoded sentence: 2\n",
      "\n",
      "-\n",
      "Input sentence: Solve -14*l + 3 = 3 for l.\n",
      "Decoded sentence: 0\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 = 4*m + 11 - 7 for m.\n",
      "Decoded sentence: -1\n",
      "\n",
      "-\n",
      "Input sentence: Solve 18*v + 30 = -12*v for v.\n",
      "Decoded sentence: -1\n",
      "\n",
      "-\n",
      "Input sentence: Solve 38 = 49*i - 60 for i.\n",
      "Decoded sentence: 2\n",
      "\n",
      "-\n",
      "Input sentence: Solve 62 = 12*a + 2 for a.\n",
      "Decoded sentence: 5\n",
      "\n",
      "-\n",
      "Input sentence: Solve 20*j + 14*j = -204 for j.\n",
      "Decoded sentence: -6\n",
      "\n",
      "-\n",
      "Input sentence: Solve -147 = -4*w - 163 for w.\n",
      "Decoded sentence: -4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 8*m - 9 = -m for m.\n",
      "Decoded sentence: 1\n",
      "\n",
      "-\n",
      "Input sentence: Solve 15*p = 6*p + 36 for p.\n",
      "Decoded sentence: 4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 30*i + 0 = -60 for i.\n",
      "Decoded sentence: -2\n",
      "\n",
      "-\n",
      "Input sentence: Solve g = -g - 2*g for g.\n",
      "Decoded sentence: 0\n",
      "\n",
      "-\n",
      "Input sentence: Solve -7*l = 69 - 76 for l.\n",
      "Decoded sentence: 1\n",
      "\n",
      "-\n",
      "Input sentence: Solve 26*z = -48*z + 518 for z.\n",
      "Decoded sentence: 7\n",
      "\n",
      "-\n",
      "Input sentence: Solve -3*d - 14*d - 17 = 0 for d.\n",
      "Decoded sentence: -1\n",
      "\n",
      "-\n",
      "Input sentence: Solve 2*a = -a + 12 for a.\n",
      "Decoded sentence: 4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 = -34*s + 26*s for s.\n",
      "Decoded sentence: 0\n",
      "\n",
      "-\n",
      "Input sentence: Solve -5 + 25 = -5*l for l.\n",
      "Decoded sentence: -4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 2642*d - 6 = 2639*d for d.\n",
      "Decoded sentence: -2\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 = 10773*c - 10764*c + 54 for c.\n",
      "Decoded sentence: -6\n",
      "\n",
      "-\n",
      "Input sentence: Solve 2*r + 12 = 18 for r.\n",
      "Decoded sentence: 3\n",
      "\n",
      "-\n",
      "Input sentence: Solve 5*c + 3*c - 3*c = 0 for c.\n",
      "Decoded sentence: 0\n",
      "\n",
      "-\n",
      "Input sentence: Solve -6*m - 60 = 6*m for m.\n",
      "Decoded sentence: -5\n",
      "\n",
      "-\n",
      "Input sentence: Solve -33 = -11*s - 0 for s.\n",
      "Decoded sentence: 3\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 = 2*m - 3 + 5 for m.\n",
      "Decoded sentence: -1\n",
      "\n",
      "-\n",
      "Input sentence: Solve 30 - 9 = 7*t for t.\n",
      "Decoded sentence: 3\n",
      "\n",
      "-\n",
      "Input sentence: Solve -3*q - 2 - 1 = 0 for q.\n",
      "Decoded sentence: -1\n",
      "\n",
      "-\n",
      "Input sentence: Solve -31*c + 50 = 236 for c.\n",
      "Decoded sentence: -6\n",
      "\n",
      "-\n",
      "Input sentence: Solve 5*q + 2 = 4*q for q.\n",
      "Decoded sentence: -2\n",
      "\n",
      "-\n",
      "Input sentence: Solve -4*j - 57 + 61 = 0 for j.\n",
      "Decoded sentence: 1\n",
      "\n",
      "-\n",
      "Input sentence: Solve -10*f - 2*f = 48 for f.\n",
      "Decoded sentence: -4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 20*o - 16*o = -8 for o.\n",
      "Decoded sentence: -2\n",
      "\n",
      "-\n",
      "Input sentence: Solve -7*u = 6*u + 91 for u.\n",
      "Decoded sentence: -7\n",
      "\n",
      "-\n",
      "Input sentence: Solve 54*y - 72*y = 72 for y.\n",
      "Decoded sentence: -4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 6*x - 8 = 2*x for x.\n",
      "Decoded sentence: 2\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 = -35*a + 65*a + 270 for a.\n",
      "Decoded sentence: -9\n",
      "\n",
      "-\n",
      "Input sentence: Solve 8*k - 629 + 573 = 0 for k.\n",
      "Decoded sentence: 6\n",
      "\n",
      "-\n",
      "Input sentence: Solve -8*j + 429 - 405 = 0 for j.\n",
      "Decoded sentence: 3\n",
      "\n",
      "-\n",
      "Input sentence: Solve 46*o = 52*o + 42 for o.\n",
      "Decoded sentence: -7\n",
      "\n",
      "-\n",
      "Input sentence: Solve -12*h + 14 = 2*h for h.\n",
      "Decoded sentence: 1\n",
      "\n",
      "-\n",
      "Input sentence: Solve -53*d + 54*d - 2 = 0 for d.\n",
      "Decoded sentence: 2\n",
      "\n",
      "-\n",
      "Input sentence: Solve -8*i - 218 = -242 for i.\n",
      "Decoded sentence: 4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 87*z = 121*z - 340 for z.\n",
      "Decoded sentence: 10\n",
      "\n",
      "-\n",
      "Input sentence: Solve 24 = -16*b + 40 for b.\n",
      "Decoded sentence: 1\n",
      "\n",
      "-\n",
      "Input sentence: Solve 154 = -39*v - 41 for v.\n",
      "Decoded sentence: -5\n",
      "\n",
      "-\n",
      "Input sentence: Solve -11*j + 14 - 47 = 0 for j.\n",
      "Decoded sentence: -3\n",
      "\n",
      "-\n",
      "Input sentence: Solve -12*b = -35*b + 92 for b.\n",
      "Decoded sentence: 4\n",
      "\n",
      "-\n",
      "Input sentence: Solve -4*u + 63 = 71 for u.\n",
      "Decoded sentence: -2\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 = -9*n - n - 50 for n.\n",
      "Decoded sentence: -5\n",
      "\n",
      "-\n",
      "Input sentence: Solve -150 = 44*p + 114 for p.\n",
      "Decoded sentence: -6\n",
      "\n",
      "-\n",
      "Input sentence: Solve -27*c + 116 = -46 for c.\n",
      "Decoded sentence: 6\n",
      "\n",
      "-\n",
      "Input sentence: Solve 0 = y + 2*y + 2*y for y.\n",
      "Decoded sentence: 0\n",
      "\n",
      "-\n",
      "Input sentence: Solve 5*n + 4 = -16 for n.\n",
      "Decoded sentence: -4\n",
      "\n",
      "-\n",
      "Input sentence: Solve -4*a - 10 = -18 for a.\n",
      "Decoded sentence: 2\n",
      "\n",
      "-\n",
      "Input sentence: Solve 9 + 7 = 4*c for c.\n",
      "Decoded sentence: 4\n",
      "\n",
      "-\n",
      "Input sentence: Solve y = 8*y - y for y.\n",
      "Decoded sentence: 0\n",
      "\n",
      "-\n",
      "Input sentence: Solve 47*p - 20*p - 108 = 0 for p.\n",
      "Decoded sentence: 4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 6*q = -181 + 139 for q.\n",
      "Decoded sentence: -7\n",
      "\n",
      "-\n",
      "Input sentence: Solve 4*o - 26 + 38 = 0 for o.\n",
      "Decoded sentence: -3\n",
      "\n",
      "-\n",
      "Input sentence: Solve -182 - 434 = -77*k for k.\n",
      "Decoded sentence: 8\n",
      "\n",
      "-\n",
      "Input sentence: Solve -11*g = 2*g + 52 for g.\n",
      "Decoded sentence: -4\n",
      "\n",
      "-\n",
      "Input sentence: Solve 20*k + 26 = -14 for k.\n",
      "Decoded sentence: -2\n",
      "\n",
      "-\n",
      "Input sentence: Solve 80*x - 103*x - 115 = 0 for x.\n",
      "Decoded sentence: -5\n",
      "\n",
      "-\n",
      "Input sentence: Solve 6 = 7*w - 9*w for w.\n",
      "Decoded sentence: -3\n",
      "\n",
      "-\n",
      "Input sentence: Solve -8*b = -0*b - 16 for b.\n",
      "Decoded sentence: 2\n",
      "\n",
      "-\n",
      "Input sentence: Solve 5 = -3*b + 8 for b.\n",
      "Decoded sentence: 1\n",
      "\n",
      "-\n",
      "Input sentence: Solve -8*y = -7*y + 5*y for y.\n",
      "Decoded sentence: 0\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for seq_index in range(100):\n",
    "    # Take one sequence (part of the training set)\n",
    "    # for trying out decoding.\n",
    "    input_seq = encoder_input_data[seq_index: seq_index + 1]\n",
    "    decoded_sentence = decode_sequence(input_seq)\n",
    "    print('-')\n",
    "    print('Input sentence:', input_texts[seq_index])\n",
    "    print('Decoded sentence:', decoded_sentence)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f5dba3f26d8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(trian_hist.history['loss'], color='C0', label='loss (train)')\n",
    "plt.plot(trian_hist.history['val_loss'], color='C0', label='loss (valid)', linestyle='--')\n",
    "plt.plot(trian_hist.history['exact_match_metric'], color='C1', label='match (train)')\n",
    "plt.plot(trian_hist.history['val_exact_match_metric'], color='C1', label='match (valid)', linestyle='--')\n",
    "plt.xlabel('epochs')\n",
    "plt.ylabel('loss')\n",
    "plt.legend(loc='best')\n",
    "plt.ylim([0,1])\n",
    "plt.grid(True, linestyle='--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f4f920c41d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(trian_hist.history['loss'], label='train')\n",
    "plt.plot(trian_hist.history['val_loss'], label='valid')\n",
    "plt.xlabel('epochs')\n",
    "plt.ylabel('loss')\n",
    "plt.legend(loc='best')\n",
    "plt.grid(True, linestyle='--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZQAAAEKCAYAAAA1qaOTAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAIABJREFUeJzt3X901Hed7/HnmwQCbRJKUgEhuIBSLFDTQto02wjdg2LV1fbWrlZdt+6qXKs96nrcbWuvK3btufVut+7W69nqbbvWrWet1ttrd1fttkhAaoqlWdIlUKALKMEClUSSKSGQ5HP/mEk2TcPwSd4z+X67fT3OyWF+fDPzzHwzvDPznfmOhRAQERHxmpR0gIiI/NeggSIiIgWhgSIiIgWhgSIiIgWhgSIiIgWhgSIiIgWhgSIiIgWhgSIiIgWhgSIiIgVRmnTARDr33HPD/Pnzx/W9J0+eZMqUKYUNKiD1+ajPR30+ae97+umnfxNCeM0ZFwwhvGq+VqxYEcZrw4YN4/7eiaA+H/X5qM8n7X3A1hDxf6ye8opUW1ubdEJe6vNRn4/6fNLeF0sDJVJ3d3fSCXmpz0d9PurzSXtfLA2USHv37k06IS/1+ajPR30+ae+L9araKC8i6XPq1Cna29s5ceJE0a5j+vTp7Ny5s2iX75WWvqlTp1JTU8PkyZPH9f0aKJHG++qwiaI+H/X5ePra29upqKhg/vz5mFnhoobp7e2lrKysKJddCGnoCyFw9OhR2tvbWbBgwbguQ095Raqqqko6IS/1+ajPx9N34sQJqqurizZMAEpL0/23cxr6zIzq6mrXI0UNlEgtLS1JJ+SlPh/1+Xj7ijlMAI4fP17Uy/dKS593PWigiIhIQWigRJoxY0bSCXmpz0d9PmnvKykpSTohr7T3xdJAiZT2Nx6pz0d9PmnvO+ussxK53qamJn7+85+fcTlP39/8zd+c8SmzdevWcccdd4z7OmJpoETauHFj0gl5qc9HfT5p70vqjYOxA8XTFzNQJkryLy14hcjuzia91OejPp9C9X3pn9rY8euuglzWoCVzKvns5a/Lu8wDDzzAXXfdxcmTJ6mvr+fzn/88b3nLW2hubqaqqopVq1bxhS98gTVr1nDVVVdx4MABTpw4wac//WnWrl0LwE9+8hM+//nP09/fz7nnnsu9997L3XffTUlJCQ888ABf+9rXePOb3/yy6/7whz9MaWkp27dv58iRI9x33318+9vfprm5mfr6er71rW8BcP311/PUU0/R09PDNddcw5e+9CXuuusufv3rX/N7v/d7nHvuuWzYsOFlHevXrwdgx44dXH755fzqV7/iM5/5DJ/61KcKejuDBkq0Yr8KxUt9PurzSXtfPjt37uTBBx/kiSeeYPLkyXziE59g48aN3HjjjVx//fVccsklLFmyhDVr1gBw3333UVVVRU9PDxdffDHvec97GBgY4GMf+xibNm1iwYIFdHR0UFVVxcc//nHKy8v53Oc+l7ehs7OT5uZmHnnkEd797nfzxBNPcM8993DxxRezbds2LrzwQm677Taqqqro7+9n9erVPPPMM3zqU5/izjvvZMOGDZx77rm88MILL+sY9Oyzz7Jhwwa6u7tZvHgx119//bjfwHg6GiiRVq1alXRCXurzUZ9Pofq++K6lBbmcsVi/fj1PP/00F198MQA9PT3MnDmTdevW8f3vf5+7776bbdu2DS1/11138fDDDwNw4MAB9uzZwwsvvMDKlSuH3hA41vflXH311ZgZF1xwAbNmzeKCCy4AYOnSpezfv58LL7yQ733ve3zzm9+kr6+P559/nh07dvCmN73pJZfz5JNPnrbjne98J2VlZZSVlTFz5kwOHz5MTU3NGG+t/LQNJVJra2vSCXmpz0d9Pmnvy7eNIYTAddddx7Zt29i2bRu7du1i3bp1HD9+nPb2dgAymQyQ3Sby+OOP09zcTGtrKxdddFFBdxkzadKkl7xjftKkSfT19bFv3z7uuOMO1q9fzzPPPMM73/nOMV/v8MstKSmhr6+vYN2DNFAidXZ2Jp2Ql/p81OeT9r7+/v7Tnrd69Woeeughjhw5AkBHRwe//OUvufHGG/ngBz/Irbfeysc+9jEAjh07xowZMzjrrLN49tlnefLJJwG49NJL2bRpE/v27Ru6DICKioqoDe4DAwN5z+/q6uLss89m+vTpHD58mB//+MdD5w2/jtN1TBQ95SUir2pLlizhy1/+MmvWrGFgYIDJkydz55138tRTT/HEE09QUlLCD37wA/7+7/+eD3zgA9x9992cf/75LF68mEsvvRSA17zmNXzzm9/k6quvZmBggJkzZ/LYY4/xrne9i2uuuYYf/vCHp90oH6O2tpaLLrqIN77x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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f4f92132f60>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(trian_hist.history['exact_match_metric'], label='exact_match')\n",
    "plt.xlabel('epochs')\n",
    "plt.ylabel('loss')\n",
    "plt.legend(loc='best')\n",
    "plt.grid(True, linestyle='--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred = model.predict_on_batch([encoder_input_data[:1024], decoder_input_data[:1024]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1024, 5, 13)"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.shape(y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "target = decoder_target_data[:1024]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1024, 5, 13)"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.shape(target)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 2,  6,  1,  1,  1],\n",
       "       [ 2,  4,  1,  1,  1],\n",
       "       [ 2, 11,  1,  1,  1],\n",
       "       ...,\n",
       "       [ 2,  7,  1,  1,  1],\n",
       "       [ 6,  1,  1,  1,  1],\n",
       "       [10,  1,  1,  1,  1]])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "argmax_pred = np.argmax(y_pred, axis=-1); argmax_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.9998703 , 0.99995303, 1.        , 0.99999046, 0.9999987 ],\n",
       "       [0.9991985 , 0.9999949 , 1.        , 0.9999999 , 1.        ],\n",
       "       [0.9997366 , 0.986476  , 1.        , 0.99978286, 0.9999335 ],\n",
       "       ...,\n",
       "       [0.99999976, 0.99999917, 1.        , 0.98244196, 0.99129385],\n",
       "       [0.99998057, 1.        , 0.99999833, 0.9999999 , 0.99999964],\n",
       "       [0.408946  , 1.        , 0.9999989 , 0.9999999 , 1.        ]],\n",
       "      dtype=float32)"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "max_pred = np.max(y_pred, axis=-1); max_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 2,  6,  1,  0,  0],\n",
       "       [ 2,  4,  1,  0,  0],\n",
       "       [ 2, 11,  1,  0,  0],\n",
       "       ...,\n",
       "       [ 2,  7,  1,  0,  0],\n",
       "       [ 6,  1,  0,  0,  0],\n",
       "       [10,  1,  0,  0,  0]])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "argmax_targ = np.argmax(target, axis=-1); argmax_targ"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "matching_batches = np.min(np.equal(argmax_pred, argmax_targ),axis=-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sum(matching_batches)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_tensor_1 = tf.placeholder('float', shape=[None, 3, 2])\n",
    "input_tensor_2 = tf.placeholder('float', shape=[None, 3, 2])\n",
    "\n",
    "results= exact_match_metric(input_tensor_1, input_tensor_2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1.0]\n"
     ]
    }
   ],
   "source": [
    "tensor_1 = np.array([[[1,0],[0,1],[1,0]]])\n",
    "tensor_2 = np.array([[[1,0],[0,1],[2,1.1]]])\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    res = sess.run([results], feed_dict={input_tensor_1: tensor_1,\n",
    "                                         input_tensor_2: tensor_2})\n",
    "print(res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1.0]"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 1, 1]])"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sum(tensor_1, axis=-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 1, 0]])"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sum(tensor_2, axis=-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'1.5.0'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "from lstm import LSTM_S2S"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "lstm = LSTM_S2S(num_encoder_tokens, num_decoder_tokens, latent_dim)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = lstm.get_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 533332 samples, validate on 133334 samples\n",
      "Epoch 1/1\n",
      "533332/533332 [==============================] - 80s 150us/step - loss: 0.6207 - exact_match_metric: 0.0534 - val_loss: 0.5724 - val_exact_match_metric: 0.0740\n"
     ]
    }
   ],
   "source": [
    "adam = Adam(lr=6e-4, beta_1=0.9, beta_2=0.995, epsilon=1e-9, decay=0.0, amsgrad=False)\n",
    "\n",
    "model.compile(optimizer=adam, loss='categorical_crossentropy', metrics=[exact_match_metric])\n",
    "trian_hist = model.fit([encoder_input_data, decoder_input_data], decoder_target_data,\n",
    "                       batch_size=batch_size,\n",
    "                       epochs=1,\n",
    "                       validation_split=0.2\n",
    "                       )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_samples = [encoder_input_data[seq_index: seq_index + 1] for seq_index in range(10)]\n",
    "input_\n",
    "\n",
    "outputs = lstm.decode_sample(input_samples,target_token_index, max_decoder_seq_length)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Solve 0 = 4*b + b + 15 for b.\n",
      "-1\n",
      "\n",
      "Solve -3*d = -0*d + 3 for d.\n",
      "-1\n",
      "\n",
      "Solve -4*h + 9 = 41 for h.\n",
      "-1\n",
      "\n",
      "Solve 2514*m = 2508*m - 24 for m.\n",
      "-1\n",
      "\n",
      "Solve -7*a + 6*a = 4 for a.\n",
      "-1\n",
      "\n",
      "Solve 288*w - 298*w = -70 for w.\n",
      "-1\n",
      "\n",
      "Solve -14*h = -4*h - 10 for h.\n",
      "-1\n",
      "\n",
      "Solve 5*w + 3 = -2 for w.\n",
      "-1\n",
      "\n",
      "Solve -15*f + 21*f - 12 = 0 for f.\n",
      "-1\n",
      "\n",
      "Solve -22 = 6*c - 4 for c.\n",
      "-1\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for i,o in zip(input_texts[:10], outputs):\n",
    "    print(i)\n",
    "    print(o)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "def exact_match_metric_old(y_true, y_pred):\n",
    "    y_pred_discrete = tf.one_hot(tf.argmax(y_pred, axis=-1), tf.shape(y_pred)[-1], axis=-1)\n",
    "\n",
    "    pred_match = tf.equal(y_pred_discrete, y_true)\n",
    "    \n",
    "    pred_match = tf.where(\n",
    "        tf.tile(\n",
    "            tf.expand_dims(\n",
    "                tf.equal(tf.reduce_sum(y_true, axis=-1),0),\n",
    "                axis=-1),\n",
    "            [1,1,tf.shape(pred_match)[-1]]),\n",
    "        tf.ones_like(pred_match, dtype=tf.bool), pred_match)\n",
    "    \n",
    "    exact_match = tf.reduce_min(tf.to_float(pred_match), axis=[1,2])\n",
    "    return tf.reduce_mean(exact_match)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class NValidationSetsCallback(Callback):\n",
    "    def __init__(self, validation_sets, verbose=0, batch_size=None):\n",
    "        \"\"\"\n",
    "        :param validation_sets:\n",
    "        dictionary mapping validation set name to validation set generator\n",
    "        :param verbose:\n",
    "        verbosity mode, 1 or 0\n",
    "        :param batch_size:\n",
    "        batch size to be used when evaluating on the additional datasets\n",
    "        \"\"\"\n",
    "        super(AdditionalValidationSets, self).__init__()\n",
    "        self.validation_sets = validation_sets\n",
    "        self.epoch = []\n",
    "        self.history = {}\n",
    "        self.verbose = verbose\n",
    "        self.batch_size = batch_size\n",
    "\n",
    "    def on_train_begin(self, logs=None):\n",
    "        self.epoch = []\n",
    "        self.history = {}\n",
    "\n",
    "    def on_epoch_end(self, epoch, logs=None):\n",
    "        logs = logs or {}\n",
    "        self.epoch.append(epoch)\n",
    "\n",
    "        # record the same values as History() as well\n",
    "        for k, v in logs.items():\n",
    "            self.history.setdefault(k, []).append(v)\n",
    "\n",
    "        # evaluate on the additional validation sets\n",
    "        for validation_set_name, validation_set in self.validation_sets.items():\n",
    "            results = self.model.evaluate_generator(validation_set,\n",
    "                                                    verbose=self.verbose,\n",
    "                                                    batch_size=self.batch_size)\n",
    "\n",
    "            for i, result in enumerate(results):\n",
    "                if i == 0:\n",
    "                    valuename = validation_set_name + '_loss'\n",
    "                else:\n",
    "                    valuename = validation_set_name + '_' + self.model.metrics[i-1].__name__\n",
    "                self.history.setdefault(valuename, []).append(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [1,2,3]\n",
    "b = [3,2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 3, 2]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum([a,b], [])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
